package com.tth.learn.addproperties.java;

import org.junit.Test;

import java.io.*;
import java.util.*;
import java.util.stream.Stream;

/**
 * @Author tth
 * @Date 2023/1/5 11:30
 */
public class java9Test {

    /**
     * java9新特性：钻石操作符的使用升级
     */
    @Test
    public void test1() {
        // Java9新特性：钻石操作符与匿名实现类可以共同使用
        Comparator<Object> com = new Comparator<>() {
            @Override
            public int compare(Object o1, Object o2) {
                return 0;
            }
        };

        // JDK7新特性：类型推断
        List<String> list = new ArrayList<>();

    }

    /**
     * java9新特性：try操作的升级--资源的关闭
     */
    @Test
    public void test2() {
        // java8之前的写法
//        InputStreamReader reader = null;
//        try {
//            reader = new InputStreamReader(System.in);
//            char[] buff = new char[1024];
//            int len;
//            while ((len = reader.read(buff)) != -1) {
//                String str = new String(buff, 0, len);
//                System.out.println(str);
//            }
//        } catch (IOException e) {
//            e.printStackTrace();
//        } finally {
//            if (null != reader) {
//                try {
//                    reader.close();
//                } catch (IOException e) {
//                    e.printStackTrace();
//                }
//            }
//        }

        // java8写法：需要自动关闭的资源的实例化必须写在try的()中
//        try(InputStreamReader reader = new InputStreamReader(System.in)) {
//            char[] buff = new char[1024];
//            int len;
//            while ((len = reader.read(buff)) != -1) {
//                String str = new String(buff, 0, len);
//                System.out.println(str);
//            }
//        } catch (IOException e) {
//            e.printStackTrace();
//        }

        // java9写法：需要自动关闭的资源的实例化可以放在try()外边，但是此时的资源对象是一个常量，无法更改。
        // 如果有多个资源需要自动关闭，在try()中用;隔开
        InputStreamReader reader = new InputStreamReader(System.in);
        OutputStreamWriter writer = new OutputStreamWriter(System.out);
        try(reader; writer) {
            char[] buff = new char[1024];
            int len;
            while ((len = reader.read(buff)) != -1) {
                String str = new String(buff, 0, len);
                System.out.println(str);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * java9之前创建只读集合。以List为例
     */
    @Test
    public void test3() {
        // java9之前的写法1
        List<String> nameList = new ArrayList<>();
        nameList.add("Bob");
        nameList.add("Jerry");
        // 将list变为只读
        nameList = Collections.unmodifiableList(nameList);
//        nameList.add("张三"); // 抛异常 UnsupportedOperationException
        System.out.println(nameList);

        // java9之前的写法2
        List<String> nameList2 = Arrays.asList("Tom", "Steven");
//        nameList2.add("张三"); // 抛异常 UnsupportedOperationException
        System.out.println(nameList2);
    }

    /**
     * java9新特性：集合工厂方法，创建只读集合
     */
    @Test
    public void test4() {
        // 创建只读List
        List<Integer> list = List.of(1, 2, 3, 4, 5);
//        list.add(6); // 抛异常 UnsupportedOperationException
        System.out.println(list);

        // 创建只读Set
        Set<String> set = Set.of("纳兰性德", "李清照", "辛弃疾");
//        set.add("李白"); // 抛异常 UnsupportedOperationException
        System.out.println(set);

        // 创建只读Set，方法一
        Map<String, Object> map = Map.of("name", "李煜", "poem", "浪淘沙令·帘外雨潺潺");
//        map.put("age", 41); // 抛异常 UnsupportedOperationExceptio
        System.out.println(map);

        // 创建只读Set，方法二
        Map<String, Object> map2 = Map.ofEntries(Map.entry("name", "李煜"), Map.entry("poem", "浪淘沙令·帘外雨潺潺"));
//        map2.put("age", 41); // 抛异常 UnsupportedOperationExceptio
        System.out.println(map2);
    }

    /**
     * java9新特性：InputStream的新方法--transferTo()
     */
    @Test
    public void test5() {
        try (InputStream is = new FileInputStream("hello.txt");
             OutputStream os = new FileOutputStream("src\\hello.txt")) {
            // 将输入流中的所有数据直接自动的复制到输出流
            is.transferTo(os);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * java9新特性：Stream API的加强一：takeWhile和dropWhile
     */
    @Test
    public void test6() {
        List<Integer> list = Arrays.asList(11, 22, 34, 54, 90, 88, 67, 7, 102);
        //takeWhile()：从开头开始查找满足指定规则的数据，直到找到不满足规则的第一个数据为止，并将这些数据返回
        list.stream().takeWhile(i -> i < 50).forEach(i -> System.out.print(i+" ")); // 11 22 34

        System.out.println("\n**************************************************");

        //dropWhile()：与takeWhile()相反。从开头开始查找不满足指定规则的数据，直到找到满足规则的第一个数据为止，并将这些数据返回
        list.stream().dropWhile(i -> i < 50).forEach(i -> System.out.print(i+" ")); // 54 90 88 67 7 102

        System.out.println("\n**************************************************");
    }

    /**
     * java9新特性：Stream API的加强二：ofNullable
     */
    @Test
    public void test7() {
        // Stream.of()参数中的多个元素，可以包含null值
        Stream<Integer> stream1 = Stream.of(1, 2, 3, null);
        System.out.println(stream1.count());

        // Stream.of()参数不能存储单个null。否则报NullPointerException
//        Stream<Object> stream2 = Stream.of(null);
//        System.out.println(stream2.count());

        // Stream.of()可以存储多个null值
        Stream<Object> stream3 = Stream.of(null, null);
        System.out.println(stream3.count());

        // Stream.ofNullable()：形参变量可以是单个的null
        Stream<Integer> stream4 = Stream.ofNullable(1);
        System.out.println(stream4.count());

        Stream<Integer> stream5 = Stream.ofNullable(null);
        System.out.println(stream5.count());
    }

    /**
     * java9新特性：Stream API的加强二：iterate
     */
    @Test
    public void test8() {
        // java8中使用Stream.terate(final T seed, final UnaryOperator<T> f) 创建无限流
        Stream.iterate(0, x -> x + 1).limit(10).forEach(System.out :: println);

        System.out.println("\n**************************************************");

        // java9中重载了Stream.iterate(T seed, Predicate<? super T> hasNext, UnaryOperator<T> next)，其中第二个参数用来表示终止条件
        Stream.iterate(0, x -> x < 8, x -> x + 1).forEach(System.out :: println);
    }

    /**
     * java9新特性：Optional的新方法--stream()
     */
    @Test
    public void test9() {
        List<String> nameList = new ArrayList<>();
        nameList.add("Bob");
        nameList.add("Jerry");

        Optional<List<String>> optional = Optional.ofNullable(nameList);
        // 将Optional实例转换为Stream实例
        Stream<List<String>> stream = optional.stream();
        stream.flatMap(x -> x.stream()).forEach(System.out :: println);
    }
}
